//备注：拷贝代码请加上作者信息
//作者：王海涛
//邮箱：1126471088@qq.com
//版本：V0.1.1
#include <stdbool.h>
#include "freemodbus_driver.h"

static uint8_t WHT_Tx_Buffer[FREEMODBUS_Max_Buff_Count];//串口底层发送缓存
static uint8_t WHT_Rx_Buffer[FREEMODBUS_Max_Buff_Count];//串口底层接收缓存


static WHT_UART_Cache_t wht_cache;
static TaskHandle_t WHT_Task_Handle;   //任务句柄
static SemaphoreHandle_t Tx_xSemaphore;//二值信号量句柄
static SemaphoreHandle_t Rx_xSemaphore;

static WHT_Ring_Queue_Handle_t WHT_Tx_Ring_Queue_Handle;
static WHT_Ring_Queue_Handle_t WHT_Rx_Ring_Queue_Handle;


/*发送空闲中断回调函数*/
static void WHT_FreeModBus_Driver_Tx_Idle_IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    xSemaphoreGiveFromISR(Tx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
/*接收空闲中断回调函数*/
static void WHT_FreeModBus_Driver_Rx_Idle_IT_Callback(void)
{
    BaseType_t xHigherPriorityTaskWoken;

    WHT_Ring_Queue.WHT_Write(WHT_Rx_Ring_Queue_Handle, wht_cache.Rx_Buf, wht_cache.Rx_Count);//留意写入失败，特别是互斥锁导致
    wht_cache.Rx_Count = 0;
    WHT_UART_BSP.WHT_DMA_Receive(&wht_cache);
    xSemaphoreGiveFromISR(Rx_xSemaphore, &xHigherPriorityTaskWoken);//释放信号量
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
/*发送FIFO数据*/
static void WHT_FreeModBus_Driver_Send_Buf(const uint8_t* tx_buf, uint32_t send_length)
{
    //等待发送完成
    while (wht_cache.Info->Tx_State != UART_Tx_Idle)
    {
        vTaskDelay(1);
    }
    wht_cache.Tx_Count = send_length;
    wht_cache.Tx_Buf = (uint8_t*)tx_buf;
    
    TickType_t Tick_Count = send_length * 10 * 1000  / FREEMODBUS_Serial_Baud_Rate;///单位ms
    if (Tick_Count >=  portTICK_RATE_MS)
        WHT_UART_BSP.WHT_DMA_Send(&wht_cache);
    else
        WHT_UART_BSP.WHT_Interrupt_Send(&wht_cache);
}

/*调试任务*/
static void WHT_FreeModBus_Task(void* parameter)
{
    Tx_xSemaphore = xSemaphoreCreateBinary();
    Rx_xSemaphore = xSemaphoreCreateBinary();

    for (; ;)
    {
        /*判断是否有需要发送的数据*/
        if (WHT_Ring_Queue.WHT_Get_Empty_State(WHT_Tx_Ring_Queue_Handle) != 0)
        {
            uint16_t length = WHT_Ring_Queue.WHT_Read(WHT_Tx_Ring_Queue_Handle, WHT_Tx_Buffer, sizeof(WHT_Tx_Buffer));
            WHT_FreeModBus_Driver_Send_Buf(WHT_Tx_Buffer, length);
            xSemaphoreTake(Tx_xSemaphore, portMAX_DELAY);//等待信号量
        }
        else
        {
            vTaskSuspend(NULL);
        }
    }
}


/*发送数据*/
void WHT_FreeModBus_Printf(const uint8_t* tx_buf, uint16_t send_length)
{
    uint16_t Length = 0;

    do
    {
        tx_buf += Length;
        send_length -= Length;
        Length = WHT_Ring_Queue.WHT_Write(WHT_Tx_Ring_Queue_Handle, tx_buf, send_length);
        vTaskResume(WHT_Task_Handle);//恢复任务运行
        if (Length == send_length)
        {
            break;
        }
        else
        {
            vTaskDelay(1);
        }
    } while (1);
}
/*获取接收状态和数据*/
uint16_t WHT_FreeModBus_Scanf(uint8_t* rx_buf, uint16_t max_receive_length)
{
    if (WHT_Ring_Queue.WHT_Get_Empty_State(WHT_Rx_Ring_Queue_Handle) == 0)
        xSemaphoreTake(Rx_xSemaphore, portMAX_DELAY);//等待信号量
    return WHT_Ring_Queue.WHT_Read(WHT_Rx_Ring_Queue_Handle, rx_buf, max_receive_length);
}
/*初始化注册*/
static void WHT_FreeModBus_Driver_Register(void)
{
    static uint8_t Tx_Ring_Queue[FREEMODBUS_Max_Buff_Count * 3];//发送环形队列
    static uint8_t Rx_Ring_Queue[FREEMODBUS_Max_Buff_Count * 3];//接收环形队列

    WHT_Ring_Queue.WHT_Register(&WHT_Tx_Ring_Queue_Handle, Tx_Ring_Queue, sizeof(Tx_Ring_Queue), FREEMODBUS_Max_Queue_Count);
    WHT_Ring_Queue.WHT_Register(&WHT_Rx_Ring_Queue_Handle, Rx_Ring_Queue, sizeof(Rx_Ring_Queue), FREEMODBUS_Max_Queue_Count);

    wht_cache.Rx_Buf_Size = FREEMODBUS_Max_Buff_Count;
    wht_cache.Rx_Count = 0;
    wht_cache.Rx_Buf = WHT_Rx_Buffer;
    wht_cache.Rx_Idle_IT_Callback = WHT_FreeModBus_Driver_Rx_Idle_IT_Callback;
    wht_cache.Tx_Idle_IT_Callback = WHT_FreeModBus_Driver_Tx_Idle_IT_Callback;

    WHT_UART_Config_t wht_config = WHT_UART_DEFAULT_CONFIG(FREEMODBUS_Serial_Name);
    wht_config.Bps = FREEMODBUS_Serial_Baud_Rate;
    WHT_UART_BSP.WHT_Register(&wht_config, &wht_cache);
    WHT_UART_BSP.WHT_Config(&wht_config, &wht_cache);
    WHT_UART_BSP.WHT_Interrupt_Receive(&wht_cache);

    xTaskCreate(WHT_FreeModBus_Task, "WHT_FreeModBus_Task", 128, NULL, configMAX_PRIORITIES, &WHT_Task_Handle);
}


/*这个函数的源路径在FreeModBus\port\portserial.c*/
bool WHT_MB_Port_Serial_Init(void)
{
    WHT_FreeModBus_Driver_Register();
    return true;
}
